<?php
/**
 * @package orinoco.framework
 * @subpackage application
 * @author Ryan Yonzon <rawswift@gmail.com>
 * @copyright Copyright 2008 Ryan Yonzon 
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 */

require(CLASS_REQUEST_DIR . 'data.class.php');
require(CLASS_REQUEST_DIR . 'holder.class.php');
require(CLASS_REQUEST_DIR . 'method.class.php');

/**
 * process application route base on URI
 */
class Router {
	
	public $_application;
	public $_controller;
	public $_method;
	public $_id;
	public $_get;
	public $_post;

	/**
	 * constructor
	 */
	public function __construct() {

	/*
	 * 1: get URI and load route configuration
	 */

		// get URI
		$_uri_request = $_SERVER['REQUEST_URI'];
		// split controller/method from parameters
		$_request_split = preg_split("/\?/", $_uri_request);
		
		// check and create $_GET object
		if(!empty($_GET)) {
			$this->createGetObject($_GET);
		}
		
		// check and create $_POST object
		if(!empty($_POST)) {
			$this->createPostObject($_POST, NULL);
		}

		// store the value for route comparison later
		$_uri = $_request_split[0];
		// get controller and method
		$_map_arr = preg_split("/\//", $_uri, 0, PREG_SPLIT_NO_EMPTY);
		
			// get routing rule from config file
			require(CONFIG_DIR . 'route.config.php');
		
		$_routing_rule = $__route__;		
		
	/*
	 * 2: processes splitted URI; route to take
	 */
		
		// iterate through the splitted URI
		foreach($_routing_rule as $_key => $_value) {
			// compare URI with the route rule
			if(preg_match($_key, $_uri)) {
				// iterate and compare the set values of the routing rule
				foreach($_value as $_k => $_v) {
					switch($_k) {
						case 'controller':
							if(strtolower($_v) == 'config_default') {
								$_routing_rule[$_key][$_k] = DEFAULT_CONTROLLER;
							} else if(strtolower($_v) == 'current') {
								$_routing_rule[$_key][$_k] = $_map_arr[0];
							}
							$this->_controller = $_routing_rule[$_key]['controller'];
							break;

						case 'action':
							if(strtolower($_v) == 'config_default') {
								$_routing_rule[$_key][$_k] = DEFAULT_METHOD;
							} else if(strtolower($_v) == 'current') {
								$_routing_rule[$_key][$_k] = $_map_arr[1];
							}
							$this->_method = $_routing_rule[$_key]['action'];							
							break;
						
						case 'id':
							$this->_id = $_map_arr[$_routing_rule[$_key]['id']];							
							break;

						default:
							break;
					}
				}
			
				$this->_application = $_routing_rule[$_key]['application'];
				
				return;
				
			}

		}
			/**
			 * @todo must do 404 redirect/error page
			 */
			throw new Exception('No route.');
			return false;
			
	}

	/**
	 * create an object copy of $_POST
	 *
	 * @param array $_arr parameter for $_POST
	 * @param string $_key_post array key
	 * @todo see what we can do with this code, too long!
	 */
	private function createPostObject($_arr, $_key_post) {
		if(isset($_key_post)) {
			$this->_post->$_key_post = new holderObject();
				foreach($_arr as $_key => $_value) {
					if(is_array($_value)) {
						$this->createPostObject($_value, $_key);
					} else {
						if(isset($this->_post->$_key_post->$_key)) {
							if(!($this->_post->$_key_post->$_key instanceof dataObject)) {
								$this->_post->$_key_post->$_key = new dataObject();
								$this->_post->$_key_post->$_key->set_value($_value);
							} // do nothing
						} else {
								$this->_post->$_key_post->$_key = new dataObject();
								$this->_post->$_key_post->$_key->set_value($_value);
						}
					}
				}
		} else {
			$this->_post = new methodObject();
				foreach($_arr as $_key => $_value) {
					if(is_array($_value)) {
						$this->createPostObject($_value, $_key);
					} else {
						if(isset($this->_post->$_key)) {
							if(!($this->_post->$_key instanceof dataObject)) {
								$this->_post->$_key = new dataObject();
								$this->_post->$_key->set_value($_value);
							} // do nothing
						} else {
								$this->_post->$_key = new dataObject();
								$this->_post->$_key->set_value($_value);
						}
					}
				}
		}
		
	}
	
	/**
	 * create an object copy of $_GET
	 *
	 * @param array $_arr parameter for $_GET
	 */
	private function createGetObject($_arr) {
		$this->_get = new holderObject();
			foreach($_arr as $_key => $_value) {
				if(isset($this->_get->$_key)) {
					if(!($this->_get->$_key instanceof dataObject)) {
						$this->_get->$_key = new dataObject();
						$this->_get->$_key->set_value($_value);
					} // do nothing
				} else {
						$this->_get->$_key = new dataObject();
						$this->_get->$_key->set_value($_value);
				}
			}
	}
	
	/**
	 * destructor
	 */
	public function __destruct() {
		unset($this);
	}

} // end class

// -EOF-